@ Echo off

SetLocal EnableExtensions EnableDelayedExpansion
Set VbsFname=%~dpn0.vbs
Set OutFname=%~dpn0.out
Echo 0=%~f0
Echo VbsFname=%VbsFname%
Echo OutFname=%OutFname%


::    RA settings
::       Shell Plugin
::          Step = Run a Shell Script
::             Directory offset = {whatever you're using}
::             xargs = {nothing}
::             Shell Script = {paste this file}
::             Interpreter = {nothing}
::             Daemon = not selected
::             Output File = not specified

:: This is the BATCH portion that takes the VBS portion and saves it to a
::    VBS file then runs CScript on it.

::    Creator:    $Creator$
::    Author:     $Author: mnemotronic $
::    File:       C:\Users\Public\Documents\Virtual Machines\VmWareShare\Source\vbs\dtcc.bat
::    Script:     DTCC.bat
::    Revision:   $Revision: 199 $
::    Header:     $Header: http://serena-teamtrack-mashups.googlecode.com/svn/vbs/util/dtcc.bat 199 2014-08-13 03:38:29Z mnemotronic $
::    Id:         $Id: dtcc.bat 199 2014-08-13 03:38:29Z mnemotronic $
::    Id:         $Date: 2014-08-13 03:38:29 +0000 (Wed, 13 Aug 2014) $


If Exist "%VbsFname%" Del /F "%VbsFname%"
:: Copy everything after line 15 to file with same name as this file but .VBS
:: The "skip" param should be the line number of the "Last Line of BATCH portion" below.
For /F "skip=50 delims=~ tokens=1*" %%I In (%0) Do echo %%I>>"%VbsFname%"
:: Run created file with CScript
c:\Windows\System32\cscript.exe "%VbsFname%" > "%OutFname%"
Echo.
Echo ------------------------ "%OutFname%" ------------------------
type "%OutFname%"
Echo ------------------------ ------------------------

Exit /B
:: ****************************************************************************
:: ****************************************************************************
:: !! ALERT!!  Every blank line in the VBScript portion must have a comment
::     char as first char, otherwise the BATCH portion outputs those lines
::     as "ECHO is off."
:: ****************************************************************************
REM :: Last Line of BATCH portion
REM ' First Line of VBScript portion
Option Explicit
'
'
'  Author:     paul_m_thompson@yahoo.com
'  File:       C:\Users\Public\Documents\Virtual Machines\VmWareShare\Source\awk\DTCC\dtcc.awk
'  Script:     DTCC.bat and DTCC.vbs
'  Revision:   $Revision: 199 $
'  Id:         $Id: dtcc.bat 199 2014-08-13 03:38:29Z mnemotronic $
'
'
'
'
CONST vbForReading = 1              ' Open a file for reading only. You can't write to this file.
CONST vbForWriting = 2              ' Open a file for writing.
CONST vbForAppending = 8            ' Open a file and write to the end of the file.
CONST vbTristateUseDefault = -2     ' Opens the file using the system default.
CONST vbTristateTrue = -1           ' Opens the file as Unicode.
CONST vbTristateFalse = 0           ' Opens the file as ASCII.
'
'
CONST PATHDELIM = "\"
CONST WORKING_DIR    = "C:\Users\Public\Documents\Virtual Machines\VmWareShare\Source\awk\DTCC"
CONST DEPLOY_DIR     = "C:\Users\Public\Documents\Virtual Machines\VmWareShare\Source\awk\DTCC\deploy"
CONST MANIFEST_FNAME = "C:\Users\Public\Documents\Virtual Machines\VmWareShare\Source\awk\DTCC\manifest.txt"
CONST PROCESS_FNAME  = "C:\Users\Public\Documents\Virtual Machines\VmWareShare\Source\awk\DTCC\process.txt"
CONST DEBUG_FLAG = True
CONST MANIFEST_FILELIST_DELIMITER = ";"
'
' ----------------------------------------------------------------------------
'
Dim obj_Args , dict_Manifest , txtstream_ManifestFile , txtstream_ProcessFile , fso
Dim regex_ManifestLine , match_ManifestLine
Dim ary_SequencedManifest()
Dim   i , rslt , strArg , str_Delimited_Manifest_Filelist , n_MaxSeqId , nSeq , _
      str_Line , str_ManifestEntryFilename , str_ManifextEntrySequenceId , _
      n_ManifestMods , manifest_entries
'
' ----------------------------------------------------------------------------
'
'  Iterate all command line args.
'     Normally there will be none - everything is hardcoded.
'     cscript DTCC.vbs UnNamed_Arg_1 /Named_Arg1:"Named Arg 1 value"
Set obj_Args = WScript.Arguments.Unnamed
For i = 0 To obj_Args.Count - 1
   WScript.Echo "DEBUG :: UnNamed Command Line Arg(" & i & "):" & obj_Args(i)
Next
'
Set obj_Args = WScript.Arguments.Named
For Each strArg in obj_Args
   WScript.Echo "DEBUG :: Named Command Line Arg[" & strArg & "]:" & obj_Args.Item(strArg)
Next
'
'
' Startup tests and diagnostics
'     Check that the Manifest file exists.  If not what do we do????
'     Chack that the Process.txt file exists.    If not what do we do????
If Not FileExists(MANIFEST_FNAME) Then
   WScript.Echo "Can't find manifest file: " & MANIFEST_FNAME & "'"
Else
   WScript.Echo "FOUND manifest file: " & MANIFEST_FNAME & "'"
End If
'
'  Every filename we find in the Manifest, delimited by by the
'     MANIFEST_FILELIST_DELIMITER character.
'  When the scanning process.txt file, check "is filename from process.txt in
'     the delimited manifest filelist string"?  An "INSTR()" is much faster
'     than iterating the manifest for each line read from process.txt file,
'     especially because process.txt will grow forever.
'
' Delete all files from the Deploy dir
If DEBUG_FLAG Then WScript.Echo "DEBUG :: Deleting all files and subdirs in the Deploy dir '" & DEPLOY_DIR & "'"
Call DeleteFiles(DEPLOY_DIR & PATHDELIM & "*")
Call DeleteFolders(DEPLOY_DIR & PATHDELIM & "*")
'
' - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- -
'  Read the manifest file and build dictionary, one entry per line.
'     Keys are filenames, values are sequence number.
'
Set fso = CreateObject("Scripting.FileSystemObject")
'
Set dict_Manifest = CreateObject("Scripting.Dictionary")
'
' Regular expression to process a line from the manifest file:
'     Skip any WHITESPACE chars
'     Capture 0 or more digits
'     Skip any WHITESPACE chars
'     Capture 0 or more non-WHITESPACE chars
Set regex_ManifestLine = GetRegEx("\s*(\d*)\s*(\S*)",true,false)
'
WScript.Echo "Reading Manifest file '" & MANIFEST_FNAME & "'"
Set txtstream_ManifestFile = fso.OpenTextFile(MANIFEST_FNAME, vbForReading, false, vbTristateUseDefault)
'
'
While Not txtstream_ManifestFile.AtEndOfStream
   str_Line = txtstream_ManifestFile.ReadLine
   WScript.echo "DEBUG :: Manifest line='" & str_Line & "'"
   Set match_ManifestLine = regex_ManifestLine.Execute(str_Line)
   If match_ManifestLine.Count > 0 Then
      str_ManifextEntrySequenceId = Trim(match_ManifestLine(0).SubMatches(0))
      str_ManifestEntryFilename = Trim(match_ManifestLine(0).SubMatches(1))
      ' Save highest Sequence ID
      nSeq = CLng(str_ManifextEntrySequenceId)
      If nSeq > n_MaxSeqId Then n_MaxSeqId = nSeq
      ' Add this filename to the dictionary
      Call dict_Manifest.Add( str_ManifestEntryFilename , match_ManifestLine(0).SubMatches(0) )
      ' append filename to the delimited list.
      str_Delimited_Manifest_Filelist = str_Delimited_Manifest_Filelist & MANIFEST_FILELIST_DELIMITER & str_ManifestEntryFilename
   Else
      ' Blank line
   End If
Wend
'
' Dont need this stuff anymore.
txtstream_ManifestFile.Close
set txtstream_ManifestFile = Nothing
'
' Append a trailing delimiter to the delimited list.
str_Delimited_Manifest_Filelist = str_Delimited_Manifest_Filelist & MANIFEST_FILELIST_DELIMITER
'
'
If DEBUG_FLAG Then wscript.echo "DEBUG :: Delimited Manifest Filelist = '" & str_Delimited_Manifest_Filelist & "'"
If DEBUG_FLAG Then wscript.echo "DEBUG :: max sequence id=" & n_MaxSeqId
'
' - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- -
'
'Now read the process.txt file and look for any entries matching what we've
'     read from the manifest.  If file from process.txt is in the manifest
'     list then that file has been deployed.  Remove that file from the
'     in-memory manifest.  Keep track of number of changes made to the
'     manifest.
'
WScript.Echo "Reading process file '" & PROCESS_FNAME & "'"
Set txtstream_ProcessFile = fso.OpenTextFile(PROCESS_FNAME, vbForReading, false, vbTristateUseDefault)
'
While Not txtstream_ProcessFile.AtEndOfStream
   str_Line = Trim(txtstream_ProcessFile.ReadLine)
   If DEBUG_FLAG Then wscript.echo "DEBUG:: Process file line '" & str_Line & "'"
   If Instr(1,str_Delimited_Manifest_Filelist, MANIFEST_FILELIST_DELIMITER & str_Line & MANIFEST_FILELIST_DELIMITER, vbTextCompare) > 0 Then
      wscript.echo "DEBUG :: Found Manifest file '" & str_Line & "' in PROCESS.TXT"
      dict_Manifest.Remove(str_Line)
      n_ManifestMods = n_ManifestMods + 1
   Else
   End If
'
Wend
'
txtstream_ProcessFile.Close
Set txtstream_ProcessFile = Nothing
'
wscript.echo CStr(n_ManifestMods) & " manifest entries modified"
'
' - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- -
'
' Copy the remaining in-memory Manifest filenames to an array.  This gets
'     them into order by sequence number.  We'll need this when we write
'     the remaining manifest entries back to the manifest file.
' wscript.echo "Before REDIM SequencedManifest array lBound=" & LBound(ary_SequencedManifest) & " uBound=" & UBound(ary_SequencedManifest)
ReDim ary_SequencedManifest(n_MaxSeqId)
If DEBUG_FLAG Then wscript.echo "DEBUG :: After REDIM SequencedManifest array lBound=" & LBound(ary_SequencedManifest) & " uBound=" & UBound(ary_SequencedManifest)
'
For Each str_Line in dict_Manifest
   If DEBUG_FLAG Then wscript.echo "create sequenced manifest list : index = " & CLng(dict_Manifest.Item(str_Line)) & " value = " & str_Line
   ary_SequencedManifest( CLng(dict_Manifest.Item(str_Line)) ) = str_Line
Next
'
If DEBUG_FLAG Then
   For i=0 to UBound(ary_SequencedManifest)
      wscript.echo "DEBUG :: ary_SequencedManifest manifest(" & i & ") == " & ary_SequencedManifest(i)
   Next
End IF
'
' - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- -
'
' If the in-memory manifest dictionary was modified save it back to the
'     manifest file.  This needs to be done in sequence order.
'
If n_ManifestMods > 0 Then
'
   ' Save updated in-memory manifest back to file.  Entries must be in sequence
   '     order.  While doing this keep track of number of valid lines we write
   '     to the manifest file.  If it's none, then the manifest list is empty
   '     which means everything has been deployed which means this deploy
   '     cycle is complete!  Woo-Hoo!
   ' Delete the manifest file as a signal to RLM.
'
   Set txtstream_ProcessFile = fso.OpenTextFile(PROCESS_FNAME, vbForWriting, false, vbTristateUseDefault)
'
   manifest_entries = 0
   For i=0 to UBound(ary_SequencedManifest)
      If Len(ary_SequencedManifest(i)) > 0 Then
         If DEBUG_FLAG Then wscript.echo "DEBUG :: ary_SequencedManifest manifest(" & i & ") == " & ary_SequencedManifest(i)
         manifest_entries = manifest_entries + 1
         Call txtstream_ProcessFile.WriteLine( FormatNumber(i,10,True) & "   " & ary_SequencedManifest(i) )
      End If
   Next
'
'
   If manifest_entries < 1 Then
      WScript.Echo "Manifest has no more files.  Deleting empty manifest file."
      Call DeleteFiles(MANIFEST_FNAME)
   End If
'
Else
   WScript.Echo "Manifest not modified."
End If
'
' - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- -
'
' For each line in manifest, if file exists in working dir then copy to
'  deploy dir and quit script immediately.
' If file doesn't exist in the working dir, then the working dir is out
'  of sync with the manifest list.  Exit immediately with error status.
'
      wscript.echo "If file from manifest list exists in working dir then copy to the deploy dir and exit post haste."
For i=0 to UBound(ary_SequencedManifest)
   If Len(ary_SequencedManifest(i)) > 0 Then
      wscript.echo "File '" & WORKING_DIR & PATHDELIM & ary_SequencedManifest(i) & "' exists."
      If FileExists(WORKING_DIR & PATHDELIM & ary_SequencedManifest(i)) Then
         ' copy file
         WScript.Echo "CopyFile(" & WORKING_DIR & PATHDELIM & ary_SequencedManifest(i) & _
            "," & DEPLOY_DIR & PATHDELIM & ary_SequencedManifest(i) & ")"
'
         rslt = fso.CopyFile(WORKING_DIR & PATHDELIM & ary_SequencedManifest(i),DEPLOY_DIR & PATHDELIM & ary_SequencedManifest(i),True)
         WScript.Echo "CopyFile result = " & rslt
      Else
         wscript.echo "File '" & ary_SequencedManifest(i) & "' does not exist" & _
            " in the working dir.  This means the working dir is out-of-sync" & _
            " with the files listed in the manifest file." & vbCrLf & _
            "Bail out with extreme prejudice."
         Call WScript.Quit(-2)
      End If
'
'
   End If
Next
'
'
' ----------------------------------------------------------------------------
' ----------------------------------------------------------------------------
'
Function FileExists(strFname)
   Dim fso
   Set fso = CreateObject("Scripting.FileSystemObject")
   FileExists = fso.FileExists(strFname)
   Set fso = Nothing
End Function
'
' ----------------------------------------------------------------------------
'  Delete specified file(s).  USE WITH CAUTION!!!
Function DeleteFiles(str_Path)
   Dim fso
   Set fso = CreateObject("Scripting.FileSystemObject")
   wscript.echo "DEBUG :: Delete files: " & str_Path
   rslt = fso.DeleteFile(str_Path, True)
   WScript.Echo "DeleteFile result = " & rslt
'
   Set fso = Nothing
End Function
' ----------------------------------------------------------------------------
'  Delete everything in the specified dir.  USE WITH CAUTION!!!
Function DeleteFolders(str_Path)
   Dim fso
   Set fso = CreateObject("Scripting.FileSystemObject")
   wscript.echo "DEBUG :: Delete folders: " & str_Path
   rslt = fso.DeleteFolder(str_Path, True)
   WScript.Echo "DeleteFolder result = " & rslt
   Set fso = Nothing
End Function
'
' ----------------------------------------------------------------------------
'  Read the DTCC Manifest file, parse it to a Dictionary object and return
'     that object.
Function ReadManifestFile(strFname, ByRef str_Delimited_Manifest_Filelist)
   Dim fso , txtstream_ManifestFile , regex_ManifestLine , match_ManifestLine
   Dim str_Line
   Set fso = CreateObject("Scripting.FileSystemObject")
   Set ReadManifestFile = CreateObject("Scripting.Dictionary")
'
   ' Regular expression to process a line from the manifest file:
   '     Skip any WHITESPACE chars
   '     Capture 0 or more non-WHITESPACE chars
   '     Skip any WHITESPACE chars
   '     Capture 0 or more digits
   Set regex_ManifestLine = GetRegEx("\s*(\d*)\s*(\S*)",true,false)
'
   WScript.Echo "DEBUG :: Reading Manifest file '" & strFname & "'"
   Set txtstream_ManifestFile = fso.OpenTextFile(strFname, vbForReading, false, vbTristateUseDefault)
'
'
   While Not txtstream_ManifestFile.AtEndOfStream
      str_Line = txtstream_ManifestFile.ReadLine
      WScript.echo "DEBUG :: Manifest line='" & str_Line & "'"
      Set match_ManifestLine = regex_ManifestLine.Execute(str_Line)
      If match_ManifestLine.Count > 0 Then
         nSeq = CLng(match_ManifestLine(0).SubMatches(0))
         str_ManifestFileEntry = Trim(match_ManifestLine(0).SubMatches(1))
         ' Save highest Sequence ID
         If nSeq > n_MaxSeqId Then n_MaxSeqId = nSeq
         Call ReadManifestFile.Add( str_ManifestFileEntry , nSeq )
         str_Delimited_Manifest_Filelist = str_Delimited_Manifest_Filelist & MANIFEST_FILELIST_DELIMITER & str_ManifestFileEntry
      Else
         ' Blank line
      End If
   Wend
'
   txtstream_ManifestFile.Close
'
   ' Append a trailing delimiter to the delimited list
   str_Delimited_Manifest_Filelist = str_Delimited_Manifest_Filelist & MANIFEST_FILELIST_DELIMITER
'
'
   set txtstream_ManifestFile = Nothing
   Set fso = Nothing
'
'
wscript.echo "DEBUG :: Delimited Manifest Filelist = '" & str_Delimited_Manifest_Filelist & "'"
End Function
'
' - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- -
' ----------------------------------------------------------------------------
' Create & return a Regular Expression object given the pattern and flags.
'  Within the body of a VBScript function we can treat the function name
'     as a declared variable.
Function GetRegEx(str_Pattern , bool_IgnoreCase , bool_Global)
   Set GetRegEx = New RegExp
'
   GetRegEx.Pattern = str_Pattern
   GetRegEx.IgnoreCase = bool_IgnoreCase
   GetRegEx.Global = bool_Global
End Function
'
'